# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-05 23:06
# File     : log_utils.py
# Project  : codebuddy_craft
# Desc     : 日志工具模块

# backend/utils/log_utils.py
"""
日志工具模块

提供日志相关的实用工具和中间件
"""

import logging
import functools
import asyncio
from typing import Any, Dict, Optional, Callable
from datetime import datetime

from .logger import (
    get_logger,
    get_security_logger,
    get_performance_logger,
    get_business_logger,
    get_system_logger
)

from fastapi import Request, Response
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.types import ASGIApp
import time
import uuid
from typing import Callable, Optional
import json

from .logger import get_logger, log_api_request


def log_function_call(logger_name: str = None, level: int = logging.INFO):
    """记录函数调用装饰器 📞"""

    def decorator(func: Callable) -> Callable:
        logger = get_logger(logger_name or func.__module__)

        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 记录函数调用
            args_repr = [repr(a) for a in args if not str(a).startswith('<')]
            kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items() if not str(v).startswith('<')]
            signature = ", ".join(args_repr + kwargs_repr)

            logger.log(level, f"📞 调用 {func.__name__}({signature})")

            try:
                result = func(*args, **kwargs)
                logger.log(level, f"✅ {func.__name__} 执行成功")
                return result
            except Exception as e:
                logger.error(f"❌ {func.__name__} 执行失败: {e}")
                raise

        @functools.wraps(func)
        async def async_wrapper(*args, **kwargs):
            # 记录异步函数调用
            args_repr = [repr(a) for a in args if not str(a).startswith('<')]
            kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items() if not str(v).startswith('<')]
            signature = ", ".join(args_repr + kwargs_repr)

            logger.log(level, f"📞 异步调用 {func.__name__}({signature})")

            try:
                result = await func(*args, **kwargs)
                logger.log(level, f"✅ {func.__name__} 执行成功")
                return result
            except Exception as e:
                logger.error(f"❌ {func.__name__} 执行失败: {e}")
                raise

        if asyncio.iscoroutinefunction(func):
            return async_wrapper
        else:
            return wrapper

    return decorator


def log_api_request(request_info: Dict[str, Any]):
    """记录API请求 🌐"""
    logger = get_logger("api")

    method = request_info.get("method", "UNKNOWN")
    path = request_info.get("path", "/")
    ip = request_info.get("client_ip", "unknown")
    user_agent = request_info.get("user_agent", "unknown")

    logger.info(
        f"🌐 API请求: {method} {path} from {ip}",
        extra={
            "event_type": "api_request",
            "method": method,
            "path": path,
            "client_ip": ip,
            "user_agent": user_agent,
            **request_info
        }
    )


def log_api_response(response_info: Dict[str, Any]):
    """记录API响应 📤"""
    logger = get_logger("api")

    status_code = response_info.get("status_code", 0)
    duration = response_info.get("duration", 0)
    path = response_info.get("path", "/")

    status_emoji = "✅" if 200 <= status_code < 300 else "⚠️" if 400 <= status_code < 500 else "❌"

    logger.info(
        f"{status_emoji} API响应: {status_code} {path} ({duration:.3f}s)",
        extra={
            "event_type": "api_response",
            "status_code": status_code,
            "duration": duration,
            "path": path,
            **response_info
        }
    )


def log_database_operation(operation: str, table: str, **kwargs):
    """记录数据库操作 🗄️"""
    logger = get_logger("database")

    logger.debug(
        f"🗄️ 数据库操作: {operation} on {table}",
        extra={
            "event_type": "database_operation",
            "operation": operation,
            "table": table,
            **kwargs
        }
    )


def log_security_event(event_type: str, description: str = None, **kwargs):
    """记录安全事件 🔒"""
    security_logger = get_security_logger()

    if event_type == "auth_attempt":
        username = kwargs.get("username", "unknown")
        ip_address = kwargs.get("ip_address", "unknown")
        success = kwargs.get("success", False)
        security_logger.log_auth_attempt(username, ip_address, success, **kwargs)
    elif event_type == "permission_denied":
        user_id = kwargs.get("user_id", "unknown")
        resource = kwargs.get("resource", "unknown")
        action = kwargs.get("action", "unknown")
        security_logger.log_permission_denied(user_id, resource, action, **kwargs)
    elif event_type == "suspicious_activity":
        security_logger.log_suspicious_activity(description or "未知可疑活动", **kwargs)
    elif event_type == "data_access":
        user_id = kwargs.get("user_id", "unknown")
        data_type = kwargs.get("data_type", "unknown")
        operation = kwargs.get("operation", "unknown")
        security_logger.log_data_access(user_id, data_type, operation, **kwargs)
    elif event_type == "security_alert":
        alert_type = kwargs.get("alert_type", "unknown")
        severity = kwargs.get("severity", "medium")
        security_logger.log_security_alert(alert_type, severity, description or "安全警报", **kwargs)
    else:
        security_logger.logger.warning(
            f"🔒 安全事件: {event_type} - {description or '无描述'}",
            extra={
                "event_type": event_type,
                "description": description,
                **kwargs
            }
        )


def log_performance_metric(name: str, value: float, unit: str = "", **kwargs):
    """记录性能指标 📊"""
    perf_logger = get_performance_logger("app")
    perf_logger.record_metric(name, value, unit, **kwargs)


def log_user_action(user_id: str, action: str, resource: str = None, **kwargs):
    """记录用户操作 👤"""
    logger = get_logger("user_actions")

    resource_str = f" on {resource}" if resource else ""

    logger.info(
        f"👤 用户操作: {user_id} {action}{resource_str}",
        extra={
            "event_type": "user_action",
            "user_id": user_id,
            "action": action,
            "resource": resource,
            "timestamp": datetime.utcnow().isoformat(),
            **kwargs
        }
    )


def log_system_event(event: str, level: int = logging.INFO, **kwargs):
    """记录系统事件 ⚙️"""
    logger = get_logger("system")

    logger.log(
        level,
        f"⚙️ 系统事件: {event}",
        extra={
            "event_type": "system_event",
            "event": event,
            **kwargs
        }
    )


def log_error_with_context(error: Exception, context: Dict[str, Any] = None):
    """记录带上下文的错误 ❌"""
    logger = get_logger("errors")

    context = context or {}

    logger.error(
        f"❌ 错误: {type(error).__name__}: {error}",
        exc_info=True,
        extra={
            "event_type": "error",
            "error_type": type(error).__name__,
            "error_message": str(error),
            **context
        }
    )


def log_cache_operation(operation: str, key: str, hit: bool = None, **kwargs):
    """记录缓存操作 💾"""
    logger = get_logger("cache")

    hit_status = " (HIT)" if hit is True else " (MISS)" if hit is False else ""

    logger.debug(
        f"💾 缓存操作: {operation} {key}{hit_status}",
        extra={
            "event_type": "cache_operation",
            "operation": operation,
            "key": key,
            "hit": hit,
            **kwargs
        }
    )


def log_file_operation(operation: str, file_path: str, **kwargs):
    """记录文件操作 📁"""
    logger = get_logger("files")

    logger.info(
        f"📁 文件操作: {operation} {file_path}",
        extra={
            "event_type": "file_operation",
            "operation": operation,
            "file_path": file_path,
            **kwargs
        }
    )


def log_ai_request(model: str, prompt_length: int, response_length: int = None, **kwargs):
    """记录AI请求 🤖"""
    logger = get_logger("ai")

    response_info = f", 响应长度: {response_length}" if response_length else ""

    logger.info(
        f"🤖 AI请求: 模型={model}, 提示长度={prompt_length}{response_info}",
        extra={
            "event_type": "ai_request",
            "model": model,
            "prompt_length": prompt_length,
            "response_length": response_length,
            **kwargs
        }
    )


def log_business_event(event_type: str, **kwargs):
    """记录业务事件 💼"""
    business_logger = get_business_logger()

    if event_type == "user_registration":
        user_id = kwargs.get("user_id", "unknown")
        email = kwargs.get("email", "unknown")
        business_logger.log_user_registration(user_id, email, **kwargs)
    elif event_type == "project_creation":
        user_id = kwargs.get("user_id", "unknown")
        project_id = kwargs.get("project_id", "unknown")
        project_name = kwargs.get("project_name", "unknown")
        business_logger.log_project_creation(user_id, project_id, project_name, **kwargs)
    elif event_type == "file_upload":
        user_id = kwargs.get("user_id", "unknown")
        file_name = kwargs.get("file_name", "unknown")
        file_size = kwargs.get("file_size", 0)
        business_logger.log_file_upload(user_id, file_name, file_size, **kwargs)
    elif event_type == "ai_interaction":
        user_id = kwargs.get("user_id", "unknown")
        model = kwargs.get("model", "unknown")
        tokens_used = kwargs.get("tokens_used", 0)
        business_logger.log_ai_interaction(user_id, model, tokens_used, **kwargs)


class LogContext:
    """日志上下文管理器 📋"""

    def __init__(self, logger_name: str, **context):
        self.logger = get_logger(logger_name)
        self.context = context
        self.start_time = None

    def __enter__(self):
        """进入上下文"""
        import time
        self.start_time = time.time()

        context_str = ", ".join(f"{k}={v}" for k, v in self.context.items())
        self.logger.info(f"🔄 开始: {context_str}")

        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文"""
        import time
        duration = time.time() - self.start_time if self.start_time else 0

        if exc_type is None:
            self.logger.info(f"✅ 完成: 耗时 {duration:.3f}s")
        else:
            self.logger.error(f"❌ 异常: {exc_type.__name__}: {exc_val}, 耗时 {duration:.3f}s")

        return False  # 不抑制异常


def create_log_context(logger_name: str, **context) -> LogContext:
    """创建日志上下文 📋"""
    return LogContext(logger_name, **context)


class PerformanceProfiler:
    """性能分析器 📊"""

    def __init__(self, name: str):
        self.name = name
        self.logger = get_performance_logger(name)
        self.start_time = None
        self.checkpoints = []

    def start(self):
        """开始分析"""
        import time
        self.start_time = time.time()
        self.checkpoints = []
        self.logger.logger.info(f"🚀 性能分析开始: {self.name}")

    def checkpoint(self, name: str):
        """添加检查点"""
        import time
        if self.start_time is None:
            self.start()

        current_time = time.time()
        elapsed = current_time - self.start_time

        if self.checkpoints:
            interval = current_time - self.checkpoints[-1]['time']
            self.logger.record_duration(f"{name}_interval", interval)

        self.checkpoints.append({
            'name': name,
            'time': current_time,
            'elapsed': elapsed
        })

        self.logger.record_duration(f"{name}_elapsed", elapsed)
        self.logger.logger.debug(f"📍 检查点 [{name}]: {elapsed:.3f}s")

    def finish(self):
        """结束分析"""
        import time
        if self.start_time is None:
            return

        total_time = time.time() - self.start_time
        self.logger.record_duration(f"{self.name}_total", total_time)

        self.logger.logger.info(
            f"🏁 性能分析完成: {self.name} 总耗时 {total_time:.3f}s",
            extra={
                "event_type": "performance_profile",
                "name": self.name,
                "total_time": total_time,
                "checkpoints": len(self.checkpoints)
            }
        )

        self.logger.flush_metrics()


def create_performance_profiler(name: str) -> PerformanceProfiler:
    """创建性能分析器 📊"""
    return PerformanceProfiler(name)


def log_with_level(logger_name: str, level: str, message: str, **kwargs):
    """使用指定级别记录日志 📝"""
    logger = get_logger(logger_name)
    log_level = getattr(logging, level.upper(), logging.INFO)

    logger.log(log_level, message, extra=kwargs)


def log_structured_event(event_type: str, **data):
    """记录结构化事件 📊"""
    logger = get_logger("structured_events")

    logger.info(
        f"📊 事件: {event_type}",
        extra={
            "event_type": event_type,
            "timestamp": datetime.utcnow().isoformat(),
            **data
        }
    )


def batch_log_events(events: list, logger_name: str = "batch"):
    """批量记录事件 📦"""
    logger = get_logger(logger_name)

    logger.info(
        f"📦 批量事件: {len(events)} 个事件",
        extra={
            "event_type": "batch_events",
            "event_count": len(events),
            "events": events
        }
    )


class AsyncLogQueue:
    """异步日志队列 🔄"""

    def __init__(self, logger_name: str, batch_size: int = 100):
        self.logger = get_logger(logger_name)
        self.batch_size = batch_size
        self.queue = []
        self._processing = False

    async def add_log(self, level: str, message: str, **kwargs):
        """添加日志到队列"""
        self.queue.append({
            "level": level.upper(),
            "message": message,
            "timestamp": datetime.utcnow().isoformat(),
            **kwargs
        })

        if len(self.queue) >= self.batch_size:
            await self.flush()

    async def flush(self):
        """刷新队列中的日志"""
        if not self.queue or self._processing:
            return

        self._processing = True
        try:
            logs_to_process = self.queue.copy()
            self.queue.clear()

            for log_entry in logs_to_process:
                level = getattr(logging, log_entry.pop("level"), logging.INFO)
                message = log_entry.pop("message")
                self.logger.log(level, message, extra=log_entry)

        finally:
            self._processing = False


def create_async_log_queue(logger_name: str, batch_size: int = 100) -> AsyncLogQueue:
    """创建异步日志队列 🔄"""
    return AsyncLogQueue(logger_name, batch_size)


# ============= 专用日志函数 =============

def log_http_request(method: str, url: str, status_code: int, duration: float, **kwargs):
    """记录HTTP请求 🌍"""
    logger = get_logger("http_client")

    status_emoji = "✅" if 200 <= status_code < 300 else "⚠️" if 400 <= status_code < 500 else "❌"

    logger.info(
        f"{status_emoji} HTTP {method} {url} -> {status_code} ({duration:.3f}s)",
        extra={
            "event_type": "http_request",
            "method": method,
            "url": url,
            "status_code": status_code,
            "duration": duration,
            **kwargs
        }
    )


def log_websocket_event(event_type: str, connection_id: str, **kwargs):
    """记录WebSocket事件 🔌"""
    logger = get_logger("websocket")

    logger.info(
        f"🔌 WebSocket {event_type}: {connection_id}",
        extra={
            "event_type": "websocket_event",
            "websocket_event_type": event_type,
            "connection_id": connection_id,
            **kwargs
        }
    )


def log_email_event(event_type: str, recipient: str, subject: str = None, **kwargs):
    """记录邮件事件 📧"""
    logger = get_logger("email")

    subject_info = f" ({subject})" if subject else ""

    logger.info(
        f"📧 邮件{event_type}: {recipient}{subject_info}",
        extra={
            "event_type": "email_event",
            "email_event_type": event_type,
            "recipient": recipient,
            "subject": subject,
            **kwargs
        }
    )


def log_scheduled_task(task_name: str, status: str, duration: float = None, **kwargs):
    """记录定时任务 ⏰"""
    logger = get_logger("scheduled_tasks")

    duration_info = f" ({duration:.3f}s)" if duration else ""
    status_emoji = "✅" if status == "success" else "❌" if status == "failed" else "🔄"

    logger.info(
        f"{status_emoji} 定时任务 {task_name}: {status}{duration_info}",
        extra={
            "event_type": "scheduled_task",
            "task_name": task_name,
            "status": status,
            "duration": duration,
            **kwargs
        }
    )


# ============= 导出所有公共函数 =============

__all__ = [
    # 装饰器
    'log_function_call',

    # API日志
    'log_api_request',
    'log_api_response',

    # 数据库日志
    'log_database_operation',

    # 安全日志
    'log_security_event',

    # 性能日志
    'log_performance_metric',

    # 用户操作日志
    'log_user_action',

    # 系统事件日志
    'log_system_event',

    # 错误日志
    'log_error_with_context',

    # 缓存日志
    'log_cache_operation',

    # 文件操作日志
    'log_file_operation',

    # AI请求日志
    'log_ai_request',

    # 业务事件日志
    'log_business_event',

    # 上下文管理器
    'LogContext',
    'create_log_context',

    # 性能分析器
    'PerformanceProfiler',
    'create_performance_profiler',

    # 工具函数
    'log_with_level',
    'log_structured_event',
    'batch_log_events',

    # 异步日志
    'AsyncLogQueue',
    'create_async_log_queue',

    # 专用日志函数
    'log_http_request',
    'log_websocket_event',
    'log_email_event',
    'log_scheduled_task',
]


class RequestLoggingMiddleware(BaseHTTPMiddleware):
    """请求日志中间件"""

    def __init__(self, app: ASGIApp, logger_name: str = "api"):
        super().__init__(app)
        self.logger = get_logger(logger_name)

    async def dispatch(self, request: Request, call_next: Callable) -> Response:
        # 生成请求ID
        request_id = str(uuid.uuid4())

        # 记录请求开始
        start_time = time.time()

        # 获取客户端信息
        client_ip = request.client.host if request.client else "unknown"
        user_agent = request.headers.get("user-agent", "unknown")

        # 记录请求详情
        self.logger.info(
            f"📝 API请求开始: {request.method} {request.url.path}",
            extra={
                'extra_fields': {
                    'request_id': request_id,
                    'method': request.method,
                    'path': request.url.path,
                    'query_params': str(request.query_params),
                    'client_ip': client_ip,
                    'user_agent': user_agent,
                    'content_type': request.headers.get("content-type"),
                    'content_length': request.headers.get("content-length")
                }
            }
        )

        # 将请求ID添加到请求状态
        request.state.request_id = request_id

        try:
            # 处理请求
            response = await call_next(request)

            # 计算响应时间
            process_time = time.time() - start_time

            # 记录响应
            self.logger.info(
                f"✅ API请求完成: {request.method} {request.url.path} - {response.status_code} ({process_time:.3f}s)",
                extra={
                    'extra_fields': {
                        'request_id': request_id,
                        'status_code': response.status_code,
                        'response_time': process_time,
                        'response_size': response.headers.get("content-length")
                    }
                }
            )

            # 添加响应头
            response.headers["X-Request-ID"] = request_id
            response.headers["X-Process-Time"] = str(process_time)

            return response

        except Exception as e:
            # 计算错误响应时间
            process_time = time.time() - start_time

            # 记录错误
            self.logger.error(
                f"❌ API请求失败: {request.method} {request.url.path} - {str(e)} ({process_time:.3f}s)",
                exc_info=True,
                extra={
                    'extra_fields': {
                        'request_id': request_id,
                        'error': str(e),
                        'response_time': process_time
                    }
                }
            )

            raise


class WebSocketLoggingMixin:
    """WebSocket日志混入类"""

    def __init__(self):
        self.logger = get_logger(f"websocket.{self.__class__.__name__}")

    def log_connection(self, client_id: str, user_id: str = None):
        """记录WebSocket连接"""
        self.logger.info(
            f"🔌 WebSocket连接建立: {client_id}",
            extra={
                'extra_fields': {
                    'client_id': client_id,
                    'user_id': user_id,
                    'event_type': 'websocket_connect'
                }
            }
        )

    def log_disconnection(self, client_id: str, reason: str = None):
        """记录WebSocket断开连接"""
        self.logger.info(
            f"🔌 WebSocket连接断开: {client_id}",
            extra={
                'extra_fields': {
                    'client_id': client_id,
                    'reason': reason,
                    'event_type': 'websocket_disconnect'
                }
            }
        )

    def log_message(self, client_id: str, message_type: str, data_size: int = None):
        """记录WebSocket消息"""
        self.logger.debug(
            f"📨 WebSocket消息: {client_id} - {message_type}",
            extra={
                'extra_fields': {
                    'client_id': client_id,
                    'message_type': message_type,
                    'data_size': data_size,
                    'event_type': 'websocket_message'
                }
            }
        )

    def log_error(self, client_id: str, error: Exception):
        """记录WebSocket错误"""
        self.logger.error(
            f"❌ WebSocket错误: {client_id} - {str(error)}",
            exc_info=True,
            extra={
                'extra_fields': {
                    'client_id': client_id,
                    'error': str(error),
                    'event_type': 'websocket_error'
                }
            }
        )


class DatabaseLoggingMixin:
    """数据库日志混入类"""

    def __init__(self):
        self.logger = get_logger(f"database.{self.__class__.__name__}")

    def log_query(self, operation: str, table: str, duration: float = None):
        """记录数据库查询"""
        self.logger.debug(
            f"🗄️ 数据库操作: {operation} {table}",
            extra={
                'extra_fields': {
                    'operation': operation,
                    'table': table,
                    'duration': duration,
                    'event_type': 'database_query'
                }
            }
        )

    def log_transaction(self, operation: str, affected_rows: int = None):
        """记录数据库事务"""
        self.logger.info(
            f"🔄 数据库事务: {operation}",
            extra={
                'extra_fields': {
                    'operation': operation,
                    'affected_rows': affected_rows,
                    'event_type': 'database_transaction'
                }
            }
        )

    def log_migration(self, version: str, operation: str, success: bool = True):
        """记录数据库迁移"""
        status = "✅ 成功" if success else "❌ 失败"
        self.logger.info(
            f"🔧 数据库迁移: {version} {operation} - {status}",
            extra={
                'extra_fields': {
                    'version': version,
                    'operation': operation,
                    'success': success,
                    'event_type': 'database_migration'
                }
            }
        )


class LLMLoggingMixin:
    """LLM日志混入类"""

    def __init__(self):
        self.logger = get_logger(f"llm.{self.__class__.__name__}")

    def log_request(self,
                    provider: str,
                    model: str,
                    prompt_tokens: int = None,
                    max_tokens: int = None):
        """记录LLM请求"""
        self.logger.info(
            f"🤖 LLM请求: {provider}/{model}",
            extra={
                'extra_fields': {
                    'provider': provider,
                    'model': model,
                    'prompt_tokens': prompt_tokens,
                    'max_tokens': max_tokens,
                    'event_type': 'llm_request'
                }
            }
        )

    def log_response(self,
                     provider: str,
                     model: str,
                     completion_tokens: int = None,
                     total_tokens: int = None,
                     duration: float = None):
        """记录LLM响应"""
        self.logger.info(
            f"✨ LLM响应: {provider}/{model} ({duration:.2f}s)",
            extra={
                'extra_fields': {
                    'provider': provider,
                    'model': model,
                    'completion_tokens': completion_tokens,
                    'total_tokens': total_tokens,
                    'duration': duration,
                    'event_type': 'llm_response'
                }
            }
        )

    def log_error(self, provider: str, model: str, error: Exception):
        """记录LLM错误"""
        self.logger.error(
            f"💥 LLM错误: {provider}/{model} - {str(error)}",
            exc_info=True,
            extra={
                'extra_fields': {
                    'provider': provider,
                    'model': model,
                    'error': str(error),
                    'event_type': 'llm_error'
                }
            }
        )


# 安全日志函数
def log_security_event(event_type: str,
                       user_id: str = None,
                       ip_address: str = None,
                       details: dict = None):
    """记录安全事件"""
    security_logger = get_logger("security")

    log_data = {
        'event_type': event_type,
        'user_id': user_id,
        'ip_address': ip_address,
        'timestamp': time.time()
    }

    if details:
        log_data.update(details)

    security_logger.warning(
        f"🔒 安全事件: {event_type}",
        extra={'extra_fields': log_data}
    )


# 业务日志函数
def log_business_event(event_type: str,
                       user_id: str = None,
                       project_id: str = None,
                       details: dict = None):
    """记录业务事件"""
    business_logger = get_logger("business")

    log_data = {
        'event_type': event_type,
        'user_id': user_id,
        'project_id': project_id,
        'timestamp': time.time()
    }

    if details:
        log_data.update(details)

    business_logger.info(
        f"📊 业务事件: {event_type}",
        extra={'extra_fields': log_data}
    )


# 性能监控函数
def log_performance_metric(metric_name: str,
                           value: float,
                           unit: str = "ms",
                           tags: dict = None):
    """记录性能指标"""
    perf_logger = get_logger("performance")

    log_data = {
        'metric_name': metric_name,
        'value': value,
        'unit': unit,
        'timestamp': time.time()
    }

    if tags:
        log_data['tags'] = tags

    perf_logger.info(f"📈 性能指标: {metric_name}={value}{unit}")


# 导出所有功能
__all__ = [
    'RequestLoggingMiddleware',
    'WebSocketLoggingMixin',
    'DatabaseLoggingMixin',
    'LLMLoggingMixin',
    'log_security_event',
    'log_business_event',
    'log_performance_metric'
]

